package org.helgoboss.caching_obr_ref_impl

import org.helgoboss.scala_additions.Logger
import org.apache.felix.bundlerepository.{Capability, Resource, Requirement, Resolver}

/**
 * Decorates another resolver with additional logging messages that make it easier to track why a certain bundle
 * has been installed.
 */
class LoggingResolver(delegate: Resolver, logger: Logger) extends Resolver {
    def add(r: Resource) {
        delegate.add(r)
    }

    def getAddedResources = delegate.getAddedResources

    def getOptionalResources = delegate.getOptionalResources

    def getReason(r: Resource) = delegate.getReason(r)

    def getRequiredResources = delegate.getRequiredResources

    def getUnsatisfiedRequirements = delegate.getUnsatisfiedRequirements

    def resolve() = {
        logger.debug("Resolving the dependencies for following resources: [" + convertToString(getAddedResources) + "] ...")
        val successful = delegate.resolve(Resolver.NO_OPTIONAL_RESOURCES)
        if (successful) {
            logger.debug("Resolved following additionally required resources:\n[" + convertToString(getRequiredResources) + "]");
            logger.debug("Resolved following optional resources:\n[" + convertToString(getOptionalResources) + "]");
            logger.debug("Reasons:\n" + convertToReasonString(getRequiredResources ++ getOptionalResources))
        }
        successful
    }
    
    private def convertToString(resources: Iterable[Resource]): String = {
        resources.map(convertToString).mkString(",\n")
    }
    
    private def convertToReasonString(resources: Iterable[Resource]) = {
        resources.map {r =>
            val requirementsString = getReason(r).map { reason =>
                convertToString(reason.getResource) + " => " + reason.getRequirement.getFilter
            }.mkString(", ")
            convertToString(r) + ": " + requirementsString
        }.mkString(",\n")
    }

    private def convertToString(r: Resource): String = r.getSymbolicName + ":" + r.getVersion

    def add(req: Requirement) {
        delegate.add(req)
    }

    def addGlobalCapability(c: Capability) {
        delegate.addGlobalCapability(c)
    }

    def deploy(flags: Int) {
        delegate.deploy(flags)
    }

    def getAddedRequirements = delegate.getAddedRequirements

    def getGlobalCapabilities = delegate.getGlobalCapabilities

    def resolve(flags: Int) = delegate.resolve(flags)
}